//
//  APIManager.m
//  Rockval
//
//  Created by TuanNT on 4/27/14.
//  Copyright (c) 2014 TNL. All rights reserved.
//

#import "APIManager.h"

/* The base api url */
static NSString *BASE_API_URL = @"http://krbecproductions.com/rockval/api/";

static NSString *LOGIN_API = @"signin.php";
static NSString *WATCHING_LIST_API = @"watchlist.php";
static NSString *RECENT_ACTIVITY_API = @"news-feed.php";
static NSString *LISTING_DETAIL_API = @"listing_details.php";
static NSString *LISTING_SEARCH_API = @"listing_search.php";
static NSString *FILTER_API = @"filter_search.php";

@implementation APIManager

static APIManager *SINGLETON = nil;

static bool isFirstAccess = YES;

#pragma mark - Public Method

+ (id)sharedInstance {
	static dispatch_once_t onceToken;
	dispatch_once(&onceToken, ^{
	    isFirstAccess = NO;
	    SINGLETON = [[super allocWithZone:NULL] init];
	});

	return SINGLETON;
}

#pragma mark - Life Cycle

+ (id)allocWithZone:(NSZone *)zone {
	return [self sharedInstance];
}

+ (id)copyWithZone:(struct _NSZone *)zone {
	return [self sharedInstance];
}

+ (id)mutableCopyWithZone:(struct _NSZone *)zone {
	return [self sharedInstance];
}

- (id)copy {
	return [[APIManager alloc] init];
}

- (id)mutableCopy {
	return [[APIManager alloc] init];
}

- (id)init {
	if (SINGLETON) {
		return SINGLETON;
	}
	if (isFirstAccess) {
		[self doesNotRecognizeSelector:_cmd];
	}
	self = [super initWithBaseURL:[NSURL URLWithString:BASE_API_URL]];
	self.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
	return self;
}

//================================ METHODS ================================
#pragma mark -
#pragma mark METHODS

- (NSURLRequest *)requestWithObject:(NSObject *)objectRequest andType:(APIType)type {
	NSMutableString *stringRequest = [[NSMutableString alloc]init];
	[stringRequest appendString:BASE_API_URL];
	if (type == APISingin) {
		ObLoginRequest *signin = (ObLoginRequest *)objectRequest;
		[stringRequest appendFormat:@"signin.php?Email=%@&Password=%@", signin.email, signin.passWord];
	}
	else if (type == APIPrimaryRole) {
		[stringRequest appendString:@"primaryrole.php"];
	}
	else if (type == APISignUp) {
		ObSignUpRequest *signUp = (ObSignUpRequest *)objectRequest;
		[stringRequest appendFormat:@"signup.php?gender=%d&firstname=%@&lastname=%@&email=%@&password=%@&telephone=%@&prole=%d", signUp.gender, signUp.firstName, signUp.lastName, signUp.email, signUp.passWord, signUp.telephone, signUp.role];
	}
	else if (type == APICountry) {
		[stringRequest appendString:@"country.php"];
	}
	else if (type == APIState) {
		NSString *strState = (NSString *)objectRequest;
		[stringRequest appendFormat:@"/state.php?country=%d", [strState integerValue]];
	}
	else if (type == APIProfile) {
		ObProfileUpdateRequest *profileUpdate = (ObProfileUpdateRequest *)objectRequest;
		profileUpdate.processType = @"Update";
		[stringRequest appendFormat:@"profile_update.php?process=%@&ID=%d&firstname=%@&lastname=%@&company=%@&website=%@&postpos=%@&email=%@&telephone=%@&prefix=%@&fax=%@&prole=%d&street_address=%@&country_id=%d&state=%d&city=%@&postcode=%@&newsletter=%@", profileUpdate.processType, profileUpdate.idProfile, profileUpdate.fisrtName, profileUpdate.lastName, profileUpdate.company, profileUpdate.website, profileUpdate.postpos, profileUpdate.email, profileUpdate.telephone, profileUpdate.prefix, profileUpdate.fax, profileUpdate.idRole, profileUpdate.streetAddress, profileUpdate.idCountry, profileUpdate.idState, profileUpdate.city, profileUpdate.postCode, profileUpdate.newsLetter];
	}
	else if (type == APIMapListing) {
		ObMapListingRequest *mapListing = (ObMapListingRequest *)objectRequest;
		[stringRequest appendFormat:@"map_listing.php?latitute=%f&longtitute=%f", mapListing.latitute, mapListing.longtitute];
	}
	else if (type == APIListingSearch) {
		NSString *keySearch = (NSString *)objectRequest;
		[stringRequest appendFormat:@"listing_search.php?type=%@", keySearch];
	}
	else if (type == APIListingDetail) {
		NSString *keySearch = (NSString *)objectRequest;
		[stringRequest appendFormat:@"listing_details.php?ID=%d", [keySearch integerValue]];
	}
	else if (type == APIRecentActivity) {
		NSString *customerID = (NSString *)objectRequest;
		[stringRequest appendFormat:@"news-feed.php?customer_id=%d", [customerID integerValue]];
	}
	else if (type == APIAddWatchList || type == APIDeleteWatchList) {
		ObActionRequest *action = (ObActionRequest *)objectRequest;
		[stringRequest appendFormat:@"watchlist.php?mode=%@&ID=%d&customer_id=%d", action.mode, action.iD, action.customerID];
	}
	else if (type == APIWatchingSale || type == APIWatchingLease) {
		ObWatchingListRequest *actionEvent = (ObWatchingListRequest *)objectRequest;
		[stringRequest appendFormat:@"watchlist.php?customer_id=%d&type=%d", actionEvent.customerID, actionEvent.type];
	}
	else {
		// nothing to do this
	}
	return [NSURLRequest requestWithURL:[NSURL URLWithString:stringRequest]
	                        cachePolicy:NSURLRequestUseProtocolCachePolicy
	                    timeoutInterval:60.0];
}

- (void)callAPIWithObject:(ObLoginRequest *)obj andType:(APIType)type
         withSuccessBlock:(void (^)(AFHTTPRequestOperation *operation, id responseObject))successBlock
             andFailBlock:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failureBlock {
	AFHTTPRequestOperation *opertation = [self HTTPRequestOperationWithRequest:[self requestWithObject:obj andType:type]
	                                                                   success: ^(AFHTTPRequestOperation *operation, id responseObject) {
	    successBlock(opertation, responseObject);
	} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
	    failureBlock(opertation, error);
	}];
	opertation.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
	[self.operationQueue addOperation:opertation];
}

- (void)loginWithObject:(ObLoginRequest *)obj andBlock:(void (^)(BOOL isSucsess, NSError *error))block {
	[self callAPIWithObject:obj andType:APISingin withSuccessBlock: ^(AFHTTPRequestOperation *operation, id responseObject) {
	    DLog(@"responseObject = %@", responseObject);
	    block(YES, nil);
	} andFailBlock: ^(AFHTTPRequestOperation *operation, NSError *error) {
	    block(NO, error);
	}];
}

- (void)listCountryWithBlock:(void (^)(NSArray *countries))block {
	[self callAPIWithObject:nil andType:APICountry withSuccessBlock: ^(AFHTTPRequestOperation *operation, id responseObject) {
	    NSMutableArray *retVal = [NSMutableArray array];
	    for (id object in(NSArray *) responseObject) {
	        [retVal addObject:[Country modelObjectWithDictionary:object]];
		}
	    block(retVal);
	} andFailBlock: ^(AFHTTPRequestOperation *operation, NSError *error) {
	    block(nil);
	}];
}

//================================ API ================================
#pragma mark -
#pragma mark API

- (void)loginWithEmail:(NSString *)email
              password:(NSString *)password
              andBlock:(void (^)(BOOL isSuccess, NSDictionary *accountDict))block {
	NSDictionary *params = @{ @"email": email,
		                      @"password": password };

	[self GET:LOGIN_API
	    parameters:params
	       success: ^(AFHTTPRequestOperation *operation, id responseObject) {
	    DLog(@"responseObject = %@", responseObject);
	    if ([[responseObject valueForKey:@"Status"] isEqualToString:@"000"]) {
	        block(YES, [responseObject valueForKey:@"details"]);
		}
	    else {
	        block(NO, nil);
		}
	} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
	    DLogError(@"error = %@", error.description);
	    block(NO, nil);
	}];
}

//================================ WATCHING ================================
#pragma mark -
#pragma mark WATCHING

/* The watching list base on customer id and type */
- (void)watchingListWithCustomerId:(NSString *)customerId
                              type:(NSString *)type
                           success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))successBlock
                           failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failureBlock {
	NSDictionary *params = @{ @"customer_id": customerId,
		                      @"type": type };
	[self GET:WATCHING_LIST_API
	    parameters:params
	       success: ^(AFHTTPRequestOperation *operation, id responseObject) {
	    DLog(@"responseObject = %@", responseObject);
	    successBlock(operation, [responseObject valueForKey:@"details"]);
	} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
	    failureBlock(operation, error);
	}];
}

/* Get watching list for sale data */
- (void)watchingListForSaleWithCustomerId:(NSString *)customerId andBlock:(void (^)(NSArray *list))block {
	[self watchingListWithCustomerId:customerId type:@"1" success: ^(AFHTTPRequestOperation *operation, id responseObject) {
	    NSMutableArray *retVal = [NSMutableArray array];
	    if ([responseObject isKindOfClass:[NSArray class]]) {
	        for (id object in(NSArray *) responseObject) {
	            if ([object isKindOfClass:[NSDictionary class]]) {
	                [retVal addObject:[Building modelObjectWithDictionary:object]];
				}
			}
		}
	    block(retVal);
	} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
	    block(nil);
	}];
}

/* Get watching list for lease data */
- (void)watchingListForLeaseWithCustomerId:(NSString *)customerId andBlock:(void (^)(NSArray *list))block {
	[self watchingListWithCustomerId:customerId type:@"2" success: ^(AFHTTPRequestOperation *operation, id responseObject) {
	    NSMutableArray *retVal = [NSMutableArray array];
	    if ([responseObject isKindOfClass:[NSArray class]]) {
	        for (id object in(NSArray *) responseObject) {
	            if ([object isKindOfClass:[NSDictionary class]]) {
	                [retVal addObject:[Building modelObjectWithDictionary:object]];
				}
			}
		}
	    block(retVal);
	} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
	    block(nil);
	}];
}

//a.	http://krbecproductions.com/rockval/api/watchlist.php?mode=AddCompare&ID=12&customer_id=12
- (void)performMode:(NSString *)mode
             itemId:(NSString *)itemId
         customerId:(NSString *)customerId
            success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))successBlock
            failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failureBlock {
	NSDictionary *params = @{ @"mode": mode,
		                      @"ID": itemId,
		                      @"customer_id": customerId };
	[self GET:WATCHING_LIST_API
	    parameters:params
	       success: ^(AFHTTPRequestOperation *operation, id responseObject) {
	    DLog(@"responseObject = %@", responseObject);
	    successBlock(operation, [responseObject valueForKey:@"details"]);
	} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
	    failureBlock(operation, error);
	}];
}

- (void)addToWatchingListForItem:(NSString *)itemId
                      customerId:(NSString *)customerId
                        andBlock:(void (^)(BOOL result))block {
	[self performMode:@"AddCompare"
	           itemId:itemId
	       customerId:customerId success: ^(AFHTTPRequestOperation *operation, id responseObject) {
	} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
	}];
}

- (void)removeFromWatchingListForItem:(NSString *)itemId
                           customerId:(NSString *)customerId
                             andBlock:(void (^)(BOOL result))block {
	[self performMode:@"DELETE"
	           itemId:itemId
	       customerId:customerId success: ^(AFHTTPRequestOperation *operation, id responseObject) {
	} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
	}];
}

//================================ NEAR BY ================================
#pragma mark -
#pragma mark NEAR BY

- (void)nearByListingForType:(NSString *)type
                    latitute:(NSString *)lat
                  longtitute:(NSString *)longt
                     success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))successBlock
                     failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failureBlock {
	NSDictionary *params = @{ @"type" : type,
		                      @"latitute" : lat,
		                      @"longtitute" : longt };
	[self GET:LISTING_SEARCH_API
	    parameters:params
	       success: ^(AFHTTPRequestOperation *operation, id responseObject) {
	    DLog(@"responseObject = %@", responseObject);
	    successBlock(operation, [responseObject valueForKey:@"details"]);
	} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
	    failureBlock(operation, error);
	}];
}

- (void)saleNearByWithLatitute:(NSString *)lat
                    longtitute:(NSString *)longt
                      andBlock:(void (^)(NSArray *list))block {
	[self nearByListingForType:@"1"
	                  latitute:lat
	                longtitute:longt
	                   success: ^(AFHTTPRequestOperation *operation, id responseObject) {
	    NSMutableArray *retVal = [NSMutableArray array];
	    if ([responseObject isKindOfClass:[NSArray class]]) {
	        for (id object in(NSArray *) responseObject) {
	            if ([object isKindOfClass:[NSDictionary class]]) {
	                [retVal addObject:[Building modelObjectWithDictionary:object]];
				}
			}
		}
	    block(retVal);
	} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
	    block(nil);
	}];
}

- (void)leaseNearByWithLatitute:(NSString *)lat
                     longtitute:(NSString *)longt
                       andBlock:(void (^)(NSArray *list))block {
	[self nearByListingForType:@"2"
	                  latitute:lat
	                longtitute:longt
	                   success: ^(AFHTTPRequestOperation *operation, id responseObject) {
	    NSMutableArray *retVal = [NSMutableArray array];
	    if ([responseObject isKindOfClass:[NSArray class]]) {
	        for (id object in(NSArray *) responseObject) {
	            if ([object isKindOfClass:[NSDictionary class]]) {
	                [retVal addObject:[Building modelObjectWithDictionary:object]];
				}
			}
		}
	    block(retVal);
	} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
	    block(nil);
	}];
}

//================================ RECENT ACTIVITY ================================
#pragma mark -
#pragma mark RECENT ACTIVITY

/* The recent activity api*/
- (void)recentActivityForCustomerWithId:(NSString *)customerId block:(void (^)(NSArray *list))block {
	NSDictionary *params = @{ @"customer_id": customerId };
	[self GET:RECENT_ACTIVITY_API
	    parameters:params
	       success: ^(AFHTTPRequestOperation *operation, id responseObject) {
	    DLog(@"responseObject = %@", responseObject);
	    NSMutableArray *retVal = [NSMutableArray array];
	    for (id object in(NSArray *)[responseObject valueForKey:@"details"]) {
	        [retVal addObject:[Activity modelObjectWithDictionary:object]];
		}
	    block(retVal);
	} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
	    block(nil);
	}];
}

//================================ SIGN UP ================================
#pragma mark -
#pragma mark SIGN UP

- (void)signUpWithObject:(ObSignUpRequest *)obj andBlock:(void (^)(BOOL isSucsess, NSError *error))block {
	NSDictionary *params = @{ @"gender": obj.gender,
		                      @"firstname": obj.firstName,
		                      @"lastname": obj.lastName,
		                      @"email": obj.email,
		                      @"password": obj.passWord,
		                      @"telephone": obj.telephone,
		                      @"prole": [NSString stringWithFormat:@"%d", obj.role],
		                      @"repassword": obj.rePassWord,
		                      @"company": obj.company,
		                      @"website": obj.website,
		                      @"address": obj.address,
		                      @"country": [NSString stringWithFormat:@"%d", obj.country],
		                      @"state": [NSString stringWithFormat:@"%d", obj.state],
		                      @"city": obj.city,
		                      @"postcode": obj.postcode };
	[self GET:@"signup.php"
	    parameters:params
	       success: ^(AFHTTPRequestOperation *operation, id responseObject) {
	    DLog(@"responseObject = %@", responseObject);
	    if ([[responseObject valueForKey:@"Status"] isEqualToString:@"000"]) {
	        block(YES, [responseObject valueForKey:@"details"]);
		}
	    else {
	        block(NO, [responseObject valueForKey:@"Message"]);
		}
	} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
	    DLogError(@"error = %@", error.description);
	    block(NO, nil);
	}];
}

//================================ FILTER ================================
#pragma mark -
#pragma mark FILTER

//type=1&keywords=abc&price_min=100&price_max=200&year_min=2010&year_max=2015&country=215&state=25&city=&zip=36001&building_size_min=12&building_size_max=25&lot_size_min=12&lot_size_max=25

- (void)filterByType:(NSString *)type
             keyword:(NSString *)keyword
            priceMin:(NSString *)priceMin
            priceMax:(NSString *)priceMax
             yearMin:(NSString *)yearMin
             yearMax:(NSString *)yearMax
             country:(NSString *)country
               state:(NSString *)state
                city:(NSString *)city
                 zip:(NSString *)zip
     buildingSizeMin:(NSString *)buildingSizeMin
     buildingSizeMax:(NSString *)buildingSizeMax
          lotSizeMin:(NSString *)lotSizeMin
          lotSizeMax:(NSString *)lotSizeMax
               block:(void (^)(NSArray *list))block {
	NSDictionary *params = @{ @"type" : type,
		                      @"keyword" : keyword,
		                      @"price_min" : priceMin,
		                      @"price_max" : priceMax,
		                      @"year_min" : yearMin,
		                      @"year_max" : yearMax,
		                      @"country" : country,
		                      @"state" : state,
		                      @"city" : city,
		                      @"zip" : zip,
		                      @"building_size_min" : buildingSizeMin,
		                      @"building_size_max" : buildingSizeMax,
		                      @"lot_size_min" : lotSizeMin,
		                      @"lot_size_max" : lotSizeMax };
	[self GET:FILTER_API
	    parameters:params
	       success: ^(AFHTTPRequestOperation *operation, id responseObject) {
	    DLog(@"responseObject = %@", responseObject);
	    NSMutableArray *retVal = [NSMutableArray array];
	    for (id object in(NSArray *)[responseObject valueForKey:@"details"]) {
	        [retVal addObject:[Activity modelObjectWithDictionary:object]];
		}
	    block(retVal);
	} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
	    block(nil);
	}];
}

@end
